package com.nowcoder.community.quartz;

import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.service.DiscussPostService;
import com.nowcoder.community.service.ElasticsearchService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.RedisKeyUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class PostScoreRefreshJob implements Job {

    private static final Logger logger = LoggerFactory.getLogger(PostScoreRefreshJob.class);

    private static final Date epoch;

    static {
        try {
            epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-08-01 00:00:00");
        } catch (ParseException e) {
            throw new RuntimeException("初始化牛客纪元失败!", e);
        }
    }

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private ElasticsearchService elasticsearchService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String postScoreKey = RedisKeyUtil.getPostScoreKey();
        BoundSetOperations<String, Object> operations = redisTemplate.boundSetOps(postScoreKey);
        if (operations.size() == 0) {
            logger.info("[PostScoreRefreshJob任务取消] 没有需要刷新分数的帖子!");
            return;
        }

        logger.info("[PostScoreRefreshJob任务开始] 待刷新分数的帖子数量: " + operations.size());
        while (operations.size() > 0) {
            this.refresh((Integer) operations.pop());
        }
        logger.info("[PostScoreRefreshJob任务结束] 所有帖子分数刷新完毕!");
    }

    private void refresh(int postId) {
        DiscussPost post = discussPostService.findDiscussPostById(postId);
        if (post == null) {
            logger.error("该帖子不存在：id = " + postId);
            return;
        }

        // score = log(精华分 + 评论数 * 10 + 点赞数 * 2) + (发布时间 - 牛客纪元)，精华分默认为 75，时间差以日为单位
        // 精华分
        int scoreOfStatus = (post.getStatus() == 1) ? 75 : 0;
        // 评论分
        int scoreOfComment = post.getCommentCount() * 10;
        // 点赞分
        int scoreOfLike = (int) (likeService.getEntityLikeCount(CommunityConstant.ENTITY_TYPE_POST, postId) * 2);
        // 时间差
        int timeDiff = (int) ((post.getCreateTime().getTime() - epoch.getTime()) / (1000 * 3600 * 24));

        double score = Math.log(Math.max(scoreOfStatus + scoreOfComment + scoreOfLike, 1)) + timeDiff;

        // 更新数据库里的帖子分数
        discussPostService.updateScore(postId, score);

        // 更新elasticsearch中的帖子
        post.setScore(score);
        elasticsearchService.saveDiscussPost(post);
    }

}
